iT邦幫忙

2022 iThome 鐵人賽

DAY 2
0

首先是 20. Valid Parentheses
https://leetcode.com/problems/valid-parentheses/

是一題標準的新手題目,寫到這題的時候真的有超懷念的感覺
中文題目翻譯:
他會給你一個變數 s 裡面「只」會包含 ’(‘ 、 ‘)’ 、 ’[‘ 、 ’]’ 、 ‘{‘ 、 ‘}’,請辨別所有的輸入是否都合乎規定。
規定大致如下:

  1. 括弧必須用相同類型的括弧閉合,例如: ‘(‘ 就必須接著 ‘)’
  2. 括弧必須用正確的順序閉合,例如 ‘[‘ 下一個接 ’)’ 就會是錯的。
  3. 每個右括弧都要對應一個相同的左括弧,例如 ’)’ 的左邊必須有一個 ’(‘ 。

基本上看到這題的時候,我就很直覺的用了以下寫法。

  1. 首先就要有一個stack,可以用來儲存找到的東西
  2. 再來去驗證是否為左括弧,是的話就丟到stack裡處理
  3. 驗證是否為右括弧,是的話從stack裡丟一個東西出來,驗證是否可以成一個pair
  4. 最後驗證stack是否為空
 class Solution:
    def isValid(self, s: str) -> bool:
        tempList = []
        for i in s:
            if i in "([{":
                tempList.append(i)
            else:
                if tempList == []:
                    return False
                temp = tempList.pop()
            if i ==")" and temp !="(":
                return False
            elif i == "]" and temp != "[":
                return False
            elif i=="}" and temp != "{":
                return False
        else:
            if tempList:
                return False
            return True  

老實說按照我以前的心態,既然已經過了就會讓它過去,而不會再去琢磨。
但個人認為,看code其實也是本事之一,要記取別人的優點,所以就算是簡單的題目我也會翻其他人的程式碼來看,特別是我也會告知正在學習的學生們,這應該是必要做的事情之一。
像個人認為以下可以學習的地方就是dict的部分,畢竟這是Python的一個特點之一,沒有好好地利用進去是很可惜的,可以減少很多if else的部分。

class Solution(object):
	def isValid(self, s):
        d = {'(':')', '{':'}','[':']'}#利用dict
        stack = []
        for i in s:
            if i in d:  # 1
                stack.append(i)
            elif len(stack) == 0 or d[stack.pop()] != i:  # 2
                return False
        return len(stack) == 0 # 3

再來是第二題的部分,遇到了 14. Longest Common Prefix
https://leetcode.com/problems/longest-common-prefix/

這題要找的是最長公共「前綴」字串,為啥特別把這部分框起來呢?因為我在做題目時忽略掉了這兩個字,導致白白花了一堆時間在驗證子字串上,還把他當成LCS來進行處理(一度想說easy的題目居然這麼難,不愧是leetcode也太有水準了),後來仔細看的時候才發現到根本不用這麼複雜,因為只需要找「前綴」。老實說這也是很多人的問題,一個眼殘真的會白花掉很多時間。

所以後來寫下來大致如下:

  1. 先找出裡面最短的字串,因為最長共同字串頂多就是裡面的最短字串
  2. 然後從頭比較,這個比較的過程當初有想過用一個一個比對就好,但後來想到python要去驗證是否有重複的部分很簡單,一個set下去馬上見真章
  3. 只要set長度為1的部分就可以加到最後答案裡面
  4. 只要有任何一次不符合,就可以結束然後 return 了(這邊return不可以放置於else裡面,避免給的側資裡有[""]<-這樣的鬼東西)
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        #這題只需要從頭開始比較即可,只要前面的字有不符合就可以跳掉,別誤會了
        d = min([len(str) for str in strs])#找出長度最短的字的長度
        i = 0#計算是否有達到最短字長度用
        result = ""#輸出
        while i < d:
            if len(set([str[i] for str in strs])) == 1:
                #將各個單字裡的第i個字母選取出來,若都一樣。則set長度必為1
                result +=strs[0][i]
            else:
                break
            i += 1
        return result

再來是第三題的部分,遇到了 459. Repeated Substring Pattern
https://leetcode.com/problems/repeated-substring-pattern/

這題雖然是easy但我卻想了一段時間,主要是在找最快執行效率的部分
我一開始的想法邏輯大致如下:

  1. 先確認總長度,因為會需要確認可不可以由部分字串的長度去進行整除的動作
  2. 開始進行組合以及確認-> 先組合一部分的字母為一個單位,接著去確認原始字串是否可以由該單位進行組成
  3. 持續進行此過程,直到找到->True或者結束->False
    所以我一開始的寫法就是正常寫法的部分
    但後來想一想,也參考了一些高手的想法發現到說,其實可以進行切割再組合判斷就好,如果捨棄原始字串的前面部分再加捨棄後面部分的原始字串,會組合新的字串,那這新的字串本身必定會包含原始字串自己。這可以大大地增加效率,應該是可以從O(n logn)變成O(n)。
class Solution:
    #1.判斷是不是由重複的東西組成
    #2.如果是的話自己一定是由兩個相同的單元組成
    #3. zfazfa -> fazfa+ zfazf -> fa zfazfa zf #摺疊
    #4. 不適用於求出重複的字串
    #一行解
    
    def repeatedSubstringPattern(self, s: str) -> bool:
        return s in s[1:] + s[:-1]
    
    #正常寫法
    # def repeatedSubstringPattern(self, s):
    #     L = len(s)
    #     for i in range(1, L//2+1):#因為最少由兩個單位組成,故直接除2
    #         if L % i == 0 and s[:i] * (L//i) == s:#首先確認是否可以整除,接下來判斷是否可以組成原本字串
    #             return 1
    #     return 0

第四題的部分,由於等等要參加Biweekly Contest 87就遞移置隔天進行編寫文章吧,要不然怕來不及參加QQ


上一篇
【第一日】前言
下一篇
Day3 隨機挑題
系列文
leetcode 30天 不中斷解題挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言